from flask import Blueprint, request, jsonify, current_app
from flask_jwt_extended import get_jwt_identity, jwt_required
import logging
import traceback
import os

from ..services.experiment_service import get_experiment_service

experiment_bp = Blueprint('experiment', __name__)
logger = logging.getLogger(__name__)

@experiment_bp.route('/health', methods=['GET'])
def health_check():
    """健康检查接口"""
    return jsonify({
        'status': 'healthy',
        'service': 'mobox-experiment',
        'version': '1.0.0'
    })

@experiment_bp.route('/resource', methods=['POST'])
def get_experiment_resource():
    """
    生成实验资源URL - 核心功能
    
    Body:
    {
        "user_id": "student001",
        "experiment_id": "exp001", 
        "course_name": "python_basics",
        "course_type": "programming"  # 可选
    }
    """
    try:
        data = request.get_json()
        
        # 验证必需参数
        required_fields = ['user_id', 'experiment_id', 'course_name']
        for field in required_fields:
            if not data.get(field):
                return jsonify({
                    'status_code': 400,
                    'data': None,
                    'message': f'缺少必需字段: {field}'
                }), 400
        
        user_id = data['user_id']
        experiment_id = data['experiment_id']
        course_name = data['course_name']
        course_type = data.get('course_type', 'default') # 获取课程类型, 默认为 'default'
        
        logger.info(f"生成实验资源URL: user={user_id}, exp={experiment_id}, course={course_name}, type={course_type}")
        
        # 调用实验服务
        service = get_experiment_service()
        # 调用新的服务函数，该函数现在负责处理工作区的创建和拷贝
        result = service.generate_experiment_url(user_id, experiment_id, course_name, course_type)
        
        # 根据服务层返回的状态码来决定HTTP响应码
        response_code = result.get('status_code', 500)
        
        return jsonify(result), response_code
        
    except Exception as e:
        logger.error(f"生成实验资源URL失败: {e}")
        logger.error(traceback.format_exc())
        return jsonify({
            'status_code': 500,
            'data': None,
            'message': f'服务器错误: {str(e)}'
        }), 500

@experiment_bp.route('/docker/start', methods=['POST'])
def start_docker_experiment():
    """
    启动Docker实验环境
    
    Body:
    {
        "user_id": "student001",
        "experiment_id": "exp001",
        "course_type": "python_basics"
    }
    """
    try:
        data = request.get_json()
        
        # 验证必需参数
        required_fields = ['user_id', 'experiment_id', 'course_type']
        for field in required_fields:
            if not data.get(field):
                return jsonify({
                    'status_code': 400,
                    'data': None,
                    'message': f'缺少必需字段: {field}'
                }), 400
        
        user_id = data['user_id']
        experiment_id = data['experiment_id']
        course_type = data['course_type']
        
        logger.info(f"启动Docker实验: user={user_id}, exp={experiment_id}, type={course_type}")
        
        # 调用实验服务
        service = get_experiment_service()
        result = service.start_docker_experiment(user_id, experiment_id, course_type)
        
        return jsonify(result), result['status_code']
        
    except Exception as e:
        logger.error(f"启动Docker实验失败: {e}")
        logger.error(traceback.format_exc())
        return jsonify({
            'status_code': 500,
            'data': None,
            'message': f'服务器错误: {str(e)}'
        }), 500

@experiment_bp.route('/docker/stop', methods=['POST'])
def stop_docker_experiment():
    """
    停止Docker实验环境
    
    Body:
    {
        "user_id": "student001",
        "experiment_id": "exp001",
        "course_type": "python_basics"
    }
    """
    try:
        data = request.get_json()
        
        # 验证必需参数
        required_fields = ['user_id', 'experiment_id', 'course_type']
        for field in required_fields:
            if not data.get(field):
                return jsonify({
                    'status_code': 400,
                    'data': None,
                    'message': f'缺少必需字段: {field}'
                }), 400
        
        user_id = data['user_id']
        experiment_id = data['experiment_id']
        course_type = data['course_type']
        
        logger.info(f"停止Docker实验: user={user_id}, exp={experiment_id}, type={course_type}")
        
        # 调用实验服务
        service = get_experiment_service()
        result = service.stop_docker_experiment(user_id, experiment_id, course_type)
        
        return jsonify(result), result['status_code']
        
    except Exception as e:
        logger.error(f"停止Docker实验失败: {e}")
        logger.error(traceback.format_exc())
        return jsonify({
            'status_code': 500,
            'data': None,
            'message': f'服务器错误: {str(e)}'
        }), 500

@experiment_bp.route('/docker/list/<user_id>', methods=['GET'])
def list_user_experiments(user_id):
    """
    列出用户的所有实验环境
    
    URL: /api/experiment/docker/list/student001
    """
    try:
        logger.info(f"获取用户实验列表: {user_id}")
        
        # 调用实验服务
        service = get_experiment_service()
        result = service.list_user_experiments(user_id)
        
        return jsonify(result), result['status_code']
        
    except Exception as e:
        logger.error(f"获取用户实验列表失败: {e}")
        logger.error(traceback.format_exc())
        return jsonify({
            'status_code': 500,
            'data': [],
            'message': f'服务器错误: {str(e)}'
        }), 500

@experiment_bp.route('/list', methods=['GET'])
def list_experiments():
    """
    获取所有实验列表
    
    URL: /api/experiment/list
    """
    try:
        logger.info("获取实验列表")
        
        # 调用实验服务获取所有实验
        service = get_experiment_service()
        
        # 从实际数据源获取实验列表，如果没有则返回空列表
        try:
            experiments = service.get_all_experiments()
        except Exception as service_error:
            logger.warning(f"实验服务获取数据失败: {service_error}")
            # 如果服务获取失败，返回空列表
            experiments = []
        
        return jsonify({
            'status_code': 200,
            'data': experiments,
            'message': '获取实验列表成功'
        }), 200
        
    except Exception as e:
        logger.error(f"获取实验列表失败: {e}")
        logger.error(traceback.format_exc())
        return jsonify({
            'status_code': 500,
            'data': [],
            'message': f'服务器错误: {str(e)}'
        }), 500

@experiment_bp.route('/status', methods=['GET'])
def get_experiment_status():
    """
    获取实验服务状态信息
    """
    try:
        import psutil
        import os
        from datetime import datetime, timezone
        
        # 获取系统信息
        cpu_percent = psutil.cpu_percent(interval=1)
        memory = psutil.virtual_memory()
        disk = psutil.disk_usage('/')
        
        status_info = {
            "service": "mobox-experiment",
            "version": "1.0.0",
            "status": "running",
            "host_ip": current_app.config.get('HOST_IP'),
            "system": {
                "cpu_percent": cpu_percent,
                "memory_percent": memory.percent,
                "disk_percent": (disk.used / disk.total) * 100
            },
            "config": {
                "course_base_path": current_app.config.get('COURSE_BASE_PATH'),
                "jupyter_port": current_app.config.get('JUPYTER_PORT'),
                "use_oss": current_app.config.get('USE_OSS'),
                "port_range": f"{current_app.config.get('PORT_RANGE_START', 8001)}-{current_app.config.get('PORT_RANGE_END', 9000)}"
            },
            "timestamp": datetime.now(timezone.utc).isoformat()
        }
        
        return jsonify({
            'status_code': 200,
            'data': status_info,
            'message': '实验服务状态正常'
        })
        
    except Exception as e:
        logger.error(f"获取实验服务状态失败: {e}")
        return jsonify({
            'status_code': 500,
            'data': None,
            'message': f'服务器错误: {str(e)}'
        }), 500

# ===== 兼容性接口 - 保持现有功能 =====

@experiment_bp.route('/resources', methods=['GET'])
def get_resources():
    """获取实验资源列表 - 兼容现有接口"""
    try:
        # 这里可以返回可用的课程/实验列表
        resources = [
            {
                'id': 'python_basics',
                'name': 'Python基础编程',
                'description': 'Python基础语法和数据类型学习',
                'type': 'programming',
                'experiments': ['exp001', 'exp002', 'exp003']
            },
            {
                'id': 'data_analysis',
                'name': '数据分析实战',
                'description': 'NumPy和Pandas数据处理',
                'type': 'data_science',
                'experiments': ['exp101', 'exp102']
            },
            {
                'id': 'machine_learning',
                'name': '机器学习入门',
                'description': 'Scikit-learn基础应用',
                'type': 'ai',
                'experiments': ['exp201', 'exp202', 'exp203']
            }
        ]
        
        return jsonify({
            'status_code': 200,
            'data': resources,
            'message': '获取资源列表成功'
        })
        
    except Exception as e:
        logger.error(f"获取资源列表失败: {e}")
        return jsonify({
            'status_code': 500,
            'data': [],
            'message': f'服务器错误: {str(e)}'
        }), 500

@experiment_bp.route('/url', methods=['POST'])
def get_experiment_url():
    """获取实验URL - 兼容现有接口"""
    try:
        data = request.get_json()
        
        # 兼容旧的参数名称
        user_id = data.get('user_id') or data.get('username', 'default_user')
        experiment_id = data.get('experiment_id') or data.get('exp_id', 'default_exp')
        course_name = data.get('course_name') or data.get('course', 'default_course')
        
        logger.info(f"兼容接口请求实验URL: user={user_id}, exp={experiment_id}, course={course_name}")
        
        # 调用统一服务
        service = get_experiment_service()
        result = service.generate_experiment_url(user_id, experiment_id, course_name)
        
        # 兼容旧格式响应
        if result['status_code'] == 200:
            return jsonify({
                'success': True,
                'url': result['data']['url'],
                'message': result['message']
            })
        else:
            return jsonify({
                'success': False,
                'error': result['message']
            }), result['status_code']
        
    except Exception as e:
        logger.error(f"兼容接口获取实验URL失败: {e}")
        return jsonify({
            'success': False,
            'error': f'服务器错误: {str(e)}'
        }), 500

# ===== V1 API 兼容性接口 - 完全兼容原测试代码 =====

# ===== V1 API 新规范接口 =====

@experiment_bp.route('/resource', methods=['POST'])
def get_experiment_resource_v1():
    """
    V1 API接口 - 根据新API规范实现
    
    请求: POST /v1/api/experiment/resource
    Body: {
        "user_id": "140",
        "experiment_id": "stu1", 
        "course_name": "segment_magic",
        "course_type": "club",
        "language": "python"
    }
    """
    try:
        data = request.get_json()
        
        # 验证必需参数
        required_fields = ['user_id', 'experiment_id', 'course_name', 'course_type', 'language']
        for field in required_fields:
            if not data.get(field):
                return jsonify({
                    'status_code': 400,
                    'data': None,
                    'message': f'Invalid request: missing required field "{field}"'
                }), 400
        
        user_id = data['user_id']
        experiment_id = data['experiment_id']
        course_name = data['course_name']
        course_type = data['course_type']
        language = data['language']
        
        # 验证course_type值
        valid_course_types = ['public', 'club', 'other']
        if course_type not in valid_course_types:
            return jsonify({
                'status_code': 400,
                'data': None,
                'message': f'Invalid course type. Must be one of: {", ".join(valid_course_types)}'
            }), 400
        
        # 验证language值
        valid_languages = ['python', 'blockly']
        if language not in valid_languages:
            return jsonify({
                'status_code': 400,
                'data': None,
                'message': f'Invalid language. Must be one of: {", ".join(valid_languages)}'
            }), 400
        
        logger.info(f"V1 API - 生成实验资源URL: user={user_id}, exp={experiment_id}, course={course_name}, type={course_type}, lang={language}")
        
        # 调用统一实验服务
        service = get_experiment_service()
        result = service.generate_experiment_url(user_id, experiment_id, course_name, course_type)
        
        # 返回符合新规范的响应格式
        if result['status_code'] == 200:
            response_data = {
                "status_code": 200,
                "data": {
                    "url": result['data']['url'],
                    "last_time": result['data']['last_time']
                },
                "message": "Resource URL generated successfully"
            }
            
            # 根据课程类型记录进度（如果是普及课的话）
            if course_type == 'public':
                logger.info(f"记录用户进度: user={user_id}, course={course_name}, exp={experiment_id}")
                # 这里可以添加进度记录逻辑
            else:
                logger.info(f"社团课不记录进度: course_type={course_type}")
            
            return jsonify(response_data), 200
        else:
            # 处理各种错误状态码
            if result['status_code'] == 404:
                return jsonify({
                    'status_code': 404,
                    'data': None,
                    'message': 'Experiment resource not found'
                }), 404
            elif result['status_code'] == 403:
                return jsonify({
                    'status_code': 403,
                    'data': None,
                    'message': 'User not authorized to access this experiment'
                }), 403
            else:
                return jsonify({
                    'status_code': 500,
                    'data': None,
                    'message': 'Internal server error'
                }), 500
        
    except Exception as e:
        logger.error(f"V1 API生成实验资源URL失败: {e}")
        logger.error(traceback.format_exc())
        return jsonify({
            'status_code': 500,
            'data': None,
            'message': 'Internal server error'
        }), 500 